package com.whfc.influx.dao.impl;

import com.whfc.common.enums.DelFlag;
import com.whfc.fse.constant.GantryMeasurement;
import com.whfc.fse.dto.FseGantryDataLogDTO;
import com.whfc.fse.entity.FseGantryDataLog;
import com.whfc.influx.dao.FseGantryDataLogDao;
import org.influxdb.InfluxDB;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
import org.influxdb.dto.Query;
import org.influxdb.impl.InfluxDBMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.*;

/**
 * @author sun_guodong
 * @date 2021-05-31
 */
@Repository
public class FseGantryDataLogDaoImpl implements FseGantryDataLogDao {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 数据库名称
     */
    private static final String database = GantryMeasurement.DATABASE;

    /**
     * 表名
     */
    private static final String measurement = GantryMeasurement.MEASUREMENT;

    /**
     * 保留策略
     */
    private static final String retentionPolicy = GantryMeasurement.RETENTION_POLICY;

    /**
     * 时间单位:秒
     */
    private static final TimeUnit timeUnit = TimeUnit.SECONDS;

    @Autowired
    private InfluxDB influxDB;

    @Autowired
    private InfluxDBMapper influxDBMapper;

    @Override
    public void insert(FseGantryDataLog record) {
        logger.info("influxdb的insert方法");
        influxDB.setDatabase(database);
        influxDB.setRetentionPolicy(retentionPolicy);
        influxDB.write(this.buildDataPoint(record));
    }

    @Override
    public void batchInsert(List<FseGantryDataLog> recordList) {
        logger.info("influxdb的batchInsert方法");
        BatchPoints.Builder batchBuiler = BatchPoints.builder();
        for (FseGantryDataLog record : recordList) {
            Point point = this.buildDataPoint(record);
            batchBuiler.point(point);
        }
        influxDB.setDatabase(database);
        influxDB.setRetentionPolicy(retentionPolicy);
        influxDB.write(batchBuiler.build());
    }


    @Override
    public List<FseGantryDataLogDTO> selectGantryDataLogListByGantryId(Integer gantryId, Date startTime, Date endTime) {
        logger.info("influxdb的selectGantryDataLogListByGantryId方法");
        Query query = select().from(database, measurement)
                .where(eq("gantryId", String.valueOf(gantryId)))
                .and(eq("delFlag", DelFlag.UNDELETE.getValue()))
                .andNested()
                .and(gte("time", startTime.toInstant().toString()))
                .and(lte("time", endTime.toInstant().toString()))
                .close()
                .orderBy(asc());
        logger.info(query.getCommand());
        List<FseGantryDataLogDTO> list = influxDBMapper.query(query, FseGantryDataLogDTO.class);
        this.transformTime(list);
        return list;
    }


    /**
     * 构建数据点
     *
     * @param record
     * @return
     */
    private Point buildDataPoint(FseGantryDataLog record) {
        logger.info("influxdb的buildDataPoint方法");
        Point.Builder builder = Point
                .measurement(measurement)
                .time(record.getTime().toInstant().getEpochSecond(), timeUnit);
        if (!ObjectUtils.isEmpty(record.getGantryId())) {
            builder.tag("gantryId", String.valueOf(record.getGantryId()));
        }
        if (!ObjectUtils.isEmpty(record.getRigidLegShift())) {
            builder.addField("rigidLegShift", record.getRigidLegShift());
        }
        if (!ObjectUtils.isEmpty(record.getSoftLegShift())) {
            builder.addField("softLegShift", record.getSoftLegShift());
        }
        if (!ObjectUtils.isEmpty(record.getShift())) {
            builder.addField("shift", record.getShift());
        }
        if (!ObjectUtils.isEmpty(record.getWindSpeed())) {
            builder.addField("windSpeed", record.getWindSpeed());
        }
        if (!ObjectUtils.isEmpty(record.getRunningTurn())) {
            builder.addField("runningTurn", record.getRunningTurn());
        }
        if (!ObjectUtils.isEmpty(record.getMainHookLiftHeight())) {
            builder.addField("mainHookLiftHeight", record.getMainHookLiftHeight());
        }
        if (!ObjectUtils.isEmpty(record.getSubHookLiftHeight())) {
            builder.addField("subHookLiftHeight", record.getSubHookLiftHeight());
        }
        if (!ObjectUtils.isEmpty(record.getSubHookLiftWeight())) {
            builder.addField("subHookLiftWeight", record.getSubHookLiftWeight());
        }
        if (!ObjectUtils.isEmpty(record.getMainHookLiftWeight())) {
            builder.addField("mainHookLiftWeight", record.getMainHookLiftWeight());
        }
        if (!ObjectUtils.isEmpty(record.getMainHookWarn())) {
            builder.addField("mainHookWarn", record.getMainHookWarn());
        }
        if (!ObjectUtils.isEmpty(record.getSubHookWarn())) {
            builder.addField("subHookWarn", record.getSubHookWarn());
        }
        if (!ObjectUtils.isEmpty(record.getMainHookWarnNum())) {
            builder.addField("mainHookWarnNum", record.getMainHookWarnNum());
        }
        if (!ObjectUtils.isEmpty(record.getSubHookWarnNum())) {
            builder.addField("subHookWarnNum", record.getSubHookWarnNum());
        }
        if (!ObjectUtils.isEmpty(record.getWindWarnNum())) {
            builder.addField("windWarnNum", record.getWindWarnNum());
        }
        if (!ObjectUtils.isEmpty(record.getDelFlag())) {
            builder.addField("delFlag", record.getDelFlag());
        }
        if (!ObjectUtils.isEmpty(record.getSubHookTimeWarnNum())) {
            builder.addField("subHookTimeWarnNum", record.getSubHookTimeWarnNum());
        }
        if (!ObjectUtils.isEmpty(record.getWindTimeWarnNum())) {
            builder.addField("windTimeWarnNum", record.getWindTimeWarnNum());
        }
        if (!ObjectUtils.isEmpty(record.getMainHookTimeWarnNum())) {
            builder.addField("mainHookTimeWarnNum", record.getMainHookTimeWarnNum());
        }
        builder.addField("serverTime", System.currentTimeMillis() / 1000);
        return builder.build();
    }

    /**
     * 时间类型转换
     *
     * @param list
     */
    private void transformTime(List<FseGantryDataLogDTO> list) {
        for (FseGantryDataLogDTO dto : list) {
            dto.setTime(Date.from(dto.getDeviceTime()));
            if (!ObjectUtils.isEmpty(dto.getServerTime())) {
                dto.setCreateTime(new Date(dto.getServerTime() * 1000));
            }
        }
    }

}
